package com.xplay.xpocker.message.action.mahjong;

import com.xplay.xpocker.entity.mahjong.MahjongCardExchangeInfo;
import com.xplay.xpocker.entity.mahjong.SwapCard;
import com.xplay.xpocker.entity.mahjong.UserSwapCard;
import com.xplay.xpocker.meta.MessageContent;
import com.xplay.xpocker.meta.realize.MahjongRoomEntity;
import com.xplay.xpocker.entity.mahjong.MahjongUserTask;
import com.xplay.xpocker.message.action.MessageAnnotation;
import com.xplay.xpocker.message.action.MessageStrategy;
import com.xplay.xpocker.meta.realize.MahjongUserChannel;
import com.xplay.xpocker.observer.SubscriptionSubject;
import com.xplay.xpocker.meta.user.MetaUserChannel;
import com.xplay.xpocker.service.mahjong.IDiskPartService;
import com.xplay.xpocker.util.CardUtil;
import com.xplay.xpocker.util.DictionaryConst;
import com.xplay.xpocker.util.JacksonStringUtil;
import com.xplay.xpocker.util.RedisUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

import static com.xplay.xpocker.util.DictionaryConst.MahjongAction.*;

/**
 * 最开始的设计是  用户需要进行摇骰子的操作
 * 后期改进了  直接将代码块引入到了  换完3张牌后的操作
 *
 * @author wanjie
 * @date 2021/3/17 21:43
 */
@MessageAnnotation(action = DISK_DICE, type = {DictionaryConst.RoomTypeConst.WZ_MAHJONG})
@Service
public class MessageDiskDice extends MessageStrategy {
    private static final Logger log = LoggerFactory.getLogger(MessageDiskDice.class);

    @Autowired
    private IDiskPartService diskPartService;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public void doMessage(MahjongUserChannel userChannel, MessageContent message, MahjongRoomEntity roomInfo) {
        // 取出订阅对象
        SubscriptionSubject subject = diskPart.get(roomInfo.getCode());
        // roomInfo.getUserTask(userChannel.getUserId()).setDealWith(true);
        int random = new Random().nextInt(6) + 1;
        roomInfo.setExchangeValue(random);
        roomInfo.setRoomTask(null);
        roomInfo.setState(DictionaryConst.MahjongRoomState.START);
        try {
            Thread.sleep(1000L);
            // 通知所有人 骰子已经摇了
            subject.notifyMessage(new MessageContent<Integer>(random, DISK_DICE), null);
            Thread.sleep(1000L);
            // 这里最好做一个延迟  不然用户无法感知  最好直接将换的牌发送给用户
            changeUserCard(roomInfo, subject);
            // 直接更新房间所有信息
            //updateRoomInfo(roomInfo);
        } catch (Exception e) {
            log.info("thread sleep  is  error................");
            e.printStackTrace();
        }

    }

    private void setSwapInfo(HashMap<String, UserSwapCard> userSwapInfo, MahjongUserChannel user) {
        if (user == null) {
            return;
        }
        UserSwapCard userSwapCards = userSwapInfo.get(user.getUserId());
        if (userSwapCards == null) {
            userSwapCards = new UserSwapCard();
            userSwapInfo.put(user.getUserId(), userSwapCards);
        }
    }

    private void changeUserCard(MahjongRoomEntity roomInfo, SubscriptionSubject subject) {
        // 开始换牌操作
        List<MahjongCardExchangeInfo> exchangeInfos = makeChangeCardArray(roomInfo.getRule().getUserCount(), roomInfo.getExchangeValue());
        HashMap<String, UserSwapCard> userSwapInfo = roomInfo.getUserSwapInfo();
        if (userSwapInfo == null) {
            userSwapInfo = new HashMap<String, UserSwapCard>();
            roomInfo.setUserSwapInfo(userSwapInfo);
        }
        for (MahjongCardExchangeInfo exchangeInfo : exchangeInfos) {
            MahjongUserChannel outUser = roomInfo.getUserInfoBySeq(exchangeInfo.getOutCard());
            MahjongUserChannel currentUser = roomInfo.getUserInfoBySeq(exchangeInfo.getCurrent());
            MahjongUserChannel inUser = roomInfo.getUserInfoBySeq(exchangeInfo.getInCard());
            setSwapInfo(userSwapInfo, inUser);
            setSwapInfo(userSwapInfo, outUser);
            setSwapInfo(userSwapInfo, currentUser);
            UserSwapCard currentUserSwapCards = userSwapInfo.get(currentUser.getUserId());
            //   1   2    3
            if (currentUser != null) {
                setSwapInfo(userSwapInfo, currentUser);
                currentUser.setSwap(false);
            }
            // 1  2  3
            if (inUser != null) {
                UserSwapCard inUserSwapCards = userSwapInfo.get(inUser.getUserId());
                setSwapInfo(userSwapInfo, inUser);
                currentUserSwapCards.setInSwapCard(new SwapCard(inUser.getUserId(), roomInfo.getUserExchangeCards().get(inUser.getUserId())));
                inUserSwapCards.setOutSwapCard(new SwapCard(currentUser.getUserId(), roomInfo.getUserExchangeCards().get(inUser.getUserId())));
                inUser.setSwap(false);
                CopyOnWriteArrayList<Integer> inCards = roomInfo.getUserExchangeCards().get(inUser.getUserId());
                roomInfo.getUserCards().get(currentUser.getUserId()).addAll(inCards);
            }

            if (outUser != null) {
                UserSwapCard outUserSwapCards = userSwapInfo.get(outUser.getUserId());
                setSwapInfo(userSwapInfo, outUser);
                currentUserSwapCards.setOutSwapCard(new SwapCard(outUser.getUserId(), roomInfo.getUserExchangeCards().get(currentUser.getUserId())));
                outUserSwapCards.setInSwapCard(new SwapCard(currentUser.getUserId(), roomInfo.getUserExchangeCards().get(currentUser.getUserId())));
                outUser.setSwap(false);
                CopyOnWriteArrayList<Integer> inCards = roomInfo.getUserExchangeCards().get(currentUser.getUserId());
                roomInfo.getUserCards().get(outUser.getUserId()).addAll(inCards);
            }
        }
        // 判断是否报叫
        // 1,1,1,2,2,2,3,3,3,10,11,12,5,6  在 打出去一张的情况下 还能胡牌
        // 一旦点了报叫的话 你打出去的牌 一定是能保证自己还能胡
        // 当 所有的牌  都交换完毕过后 判断所有的用户是否报叫 如果报叫 添加 报叫指令 并发出给所有用户
        HashMap<String, CopyOnWriteArrayList<Integer>> userCards = roomInfo.getUserCards();
        boolean loading = false;
        for (Map.Entry<String, CopyOnWriteArrayList<Integer>> entry : userCards.entrySet()) {
            MetaUserChannel cardUserChannel = roomInfo.getUserInfoByUserId(entry.getKey());
            //  ----------------------发完牌过后需要报叫处理------------------------
            if (entry.getValue().size() == DictionaryConst.MahjongConstant.LEISURE_COUNT) {
                // 判断用户是否可以胡牌
                List<Integer> userHuCard = CardUtil.checkUserHuCard(entry.getValue());
                if (userHuCard.size() > 0) {
                    loading = true;
                    roomInfo.addTask(new MahjongUserTask(roomInfo.getUserInfoByUserId(entry.getKey()).getUserId(), CARD_CALL, ACTION_PASS));
                    senMessage(getCtxByUserId(roomInfo.getCode(), cardUserChannel.getUserId()), new MessageContent<MahjongUserTask>(roomInfo.getUserTask(cardUserChannel.getUserId()), ACTION_TIPS));
                }
            } else if (entry.getValue().size() == DictionaryConst.MahjongConstant.BANKER_COUNT) {
                boolean sendActionTips = false;
                if (CardUtil.checkUserHu(entry.getValue())) {
                    sendActionTips = true;
                    roomInfo.addTask(new MahjongUserTask(roomInfo.getUserInfoByUserId(entry.getKey()).getUserId(), CARD_HU));
                }
                if (CardUtil.checkUserCallCard(entry.getValue()).size() > 0) {
                    sendActionTips = true;
                    roomInfo.addTask(new MahjongUserTask(roomInfo.getUserInfoByUserId(entry.getKey()).getUserId(), CARD_CALL));
                }
                if (sendActionTips) {
                    roomInfo.addTask(new MahjongUserTask(roomInfo.getUserInfoByUserId(entry.getKey()).getUserId(), ACTION_PASS));
                    senMessage(getCtxByUserId(roomInfo.getCode(), cardUserChannel.getUserId()), new MessageContent<MahjongUserTask>(roomInfo.getUserTask(cardUserChannel.getUserId()), ACTION_TIPS));
                }
            }
        }
        // 讲换的牌 给 各位用户   发送消息
        // 将拿到的牌 转发给  用户
        for (Map.Entry<String, MahjongUserChannel> entry : roomInfo.getAllUserInfo().entrySet()) {
            entry.getValue().setUserSwapCard(roomInfo.getUserSwapInfo().get(entry.getKey()));
            senMessage(subject.getUserChannelByUserId(entry.getKey()), new MessageContent<UserSwapCard>(roomInfo.getUserSwapInfo().get(entry.getKey()), EXCHANGE_CARD, entry.getKey()));
        }
        // 如果有人报叫的话 这里 是不能给庄家添加出牌指令的
        if (!loading) {
            addBankerExport(roomInfo);
        }
    }

    public static void main(String[] args) {

        System.out.println(makeChangeCardArray(3, 1));
    }


    // 使用枚举将情况列举完毕
    private static List<MahjongCardExchangeInfo> makeChangeCardArray(Integer userCount, Integer exchangeValue) {
        List<MahjongCardExchangeInfo> result = new ArrayList<>();
        if (userCount == DictionaryConst.MahjongRoomUserIndexConst.THREE) {
            if (exchangeValue % 2 == 0) {
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.THREE, DictionaryConst.MahjongRoomUserIndexConst.TWO));
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.TWO, null, DictionaryConst.MahjongRoomUserIndexConst.THREE));
            } else {
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.TWO, DictionaryConst.MahjongRoomUserIndexConst.THREE));
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.THREE, null, DictionaryConst.MahjongRoomUserIndexConst.TWO));
            }
            return result;
        } else if (userCount == DictionaryConst.MahjongRoomUserIndexConst.TWO) {
            result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.TWO, DictionaryConst.MahjongRoomUserIndexConst.TWO));
            return result;
        }
        if (exchangeValue == DictionaryConst.MahjongDiceConst.TWO || exchangeValue == DictionaryConst.MahjongDiceConst.SIX) {
            // 交换棋牌  庄家有可能是 1,2,3,4
            if (userCount == DictionaryConst.MahjongRoomUserIndexConst.FOUR) {
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.THREE, DictionaryConst.MahjongRoomUserIndexConst.THREE));
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.TWO, DictionaryConst.MahjongRoomUserIndexConst.FOUR, DictionaryConst.MahjongRoomUserIndexConst.FOUR));
            }
            // 右边
        } else if (exchangeValue == DictionaryConst.MahjongDiceConst.ONE || exchangeValue == DictionaryConst.MahjongDiceConst.FIVE) {
            if (userCount == DictionaryConst.MahjongRoomUserIndexConst.FOUR) {
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.TWO, DictionaryConst.MahjongRoomUserIndexConst.FOUR));
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.THREE, DictionaryConst.MahjongRoomUserIndexConst.FOUR, DictionaryConst.MahjongRoomUserIndexConst.TWO));
            }
        } else {
            if (userCount == DictionaryConst.MahjongRoomUserIndexConst.FOUR) {
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.ONE, DictionaryConst.MahjongRoomUserIndexConst.FOUR, DictionaryConst.MahjongRoomUserIndexConst.TWO));
                result.add(new MahjongCardExchangeInfo(DictionaryConst.MahjongRoomUserIndexConst.THREE, DictionaryConst.MahjongRoomUserIndexConst.TWO, DictionaryConst.MahjongDiceConst.FOUR));
            }
        }
        return result;
    }
}
